package com.packet.cheng.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.packet.cheng.dto.UserParamDTO;
import com.packet.cheng.entity.TestUser;
import com.packet.cheng.entity.User;
import com.packet.cheng.mapper.UserMapper;
import com.packet.cheng.service.UserService;
import com.packet.cheng.util.DateUtil;
import com.packet.cheng.util.MD5Util;
import com.packet.cheng.util.R;
import com.packet.cheng.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.xml.bind.ValidationException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author 张在成
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper  userMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    public  static Map<String,Object> cache = new HashMap<>();


    @Override
    public R<User> login(String token,String username, String password) throws Exception {
        //根据token获取用户信息
        User user = (User) redisTemplate.opsForValue().get(token);
        if (!Objects.isNull(user)){
            return  R.data(200,"登录成功",token);
        }
        //对密码进行加密与数据库的密码进行比较
        String pwd= MD5Util.MD5(password);
        try {
            User login = userMapper.login(username, pwd);
            if (login==null){
                return  R.data(400,"用户不存在");
            }
            if (login.getIsValid()==0){
                return  R.data(400,"用户信息已失效");
            }
            //生成加密后的字符串
            token=MD5Util.MD5(login.getId()+"--"+login.getPassword());
            redisTemplate.opsForValue().set(token,login,100*60, TimeUnit.SECONDS);
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.data(200,"登录成功",token);
    }

    @Override
    public boolean insertUser(UserParamDTO paramDTO) throws Exception {
        User user1=new User();
        BeanUtils.copyProperties(paramDTO,user1);
        //添加用户信息的时候，判断该用户的名称和昵称是否存在
        Integer i = userMapper.countNameAndNick(user1);
        if (i>0){
            throw  new Exception("用户名或者昵称已经存在");
        }
        insert(paramDTO);
        return false;
    }

    private  boolean  insert(UserParamDTO paramDTO){
        User userinfo=new User();
        userinfo.setCreateDate(DateUtil.getCurrentDate(new Date()));
        userinfo.setUpdateDate(DateUtil.getCurrentDate(new Date()));
        userinfo.setIsValid(1);
        paramDTO.setPassword(MD5Util.MD5(paramDTO.getPassword()));
        BeanUtils.copyProperties(paramDTO,userinfo);
        boolean b = userMapper.insertUser(userinfo);
        if (b){
            return true;
        }
        return false;
    }

//    @PostConstruct
//    public  void  init(){
//        List<User> users = userMapper.selectUser();
//        cache.put("user",users);
//        cache.put("userVersion",users);
//    }
//
//    public  static  Object  get(String key){
//        Object o = cache.get(key);
//        return o;
//    }


    @Override
    public List<User> selectUser() {
        List<User> user =null;
        try {
            user=userMapper.selectUser();
            if (user==null){
                throw new Exception("没有用户信息");
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return user;
    }

    @Override
    public User selectUserById(UserParamDTO userParamDTO) throws Exception {
        if (StringUtils.isEmpty(String.valueOf(userParamDTO.getId()))){
            throw new ValidationException("用户id不能为空");
        }
        User userParam=new User();
        BeanUtils.copyProperties(userParamDTO,userParam);
        User user = userMapper.selectUserById(userParam);
        if (StringUtils.isEmpty(user.toString())){
            throw new Exception("没有该用户");
        }
        return user;
    }

    /**
     * 通过用户名查询用户信息
     *
     * @param username
     * @return
     */
    @Override
    public List<User> selectUserByName(String username) throws Exception {
        if (StringUtil.isBlank(username)){
            List<User> userList = userMapper.selectUser();
            return  userList;
        }
        UserParamDTO userParamDTO =new UserParamDTO();
        userParamDTO.setUsername(username);
        User userParam=new User();
        BeanUtils.copyProperties(userParamDTO,userParam);
        List<User> users = userMapper.selectUserByName(userParam);
        users.forEach(f->{
            if (StringUtil.isBlank(f.getUsername())){
                try {
                    throw new Exception("没有查询到该用户");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            System.out.println(f);
        });
        return users;
    }

    /**
     * 登录认证
     *
     * @param token
     */
    @Override
    public R<User> loginAuthticate(String token) throws Exception {
        User user = (User)redisTemplate.opsForValue().get(token);
        log.info("用户信息："+user);
        if (Objects.isNull(user)){
            return R.data(400,"您还没有登录该系统",null);
        }
        return  R.data(200,"登录成功",user);
    }


    // 模拟死锁：两个业务按照不同顺序执行，互相等待锁的释放，日志出现DeadLock证明出现死锁
    // 解决方式：按照同一顺序访问表，即可解决
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateUser(User user) throws InterruptedException {
        int i = userMapper.updateUserInfo(user.getUsername(),user.getId());
        TimeUnit.SECONDS.sleep(10);
        int i1 = userMapper.updateTestUser(user.getUsername(), user.getId());
        System.out.println("updateUser:更新成功");
        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateTestUser(TestUser user) {
        userMapper.updateUserInfo(user.getName(),user.getId());
        int i = userMapper.updateTestUser(user.getName(),user.getId());
        System.out.println("updateTestUser:更新成功");
        return 1;
    }
}
